# -*- coding: UTF-8 -*-
'''
Created on Jan 24, 2010

@author: pguedes
'''
from utils import notification
import xbmc, xbmcgui, xbmcplugin
import urllib, os, sys, logging

log = logging.getLogger("pluginsupport")

CACHE_PATH_FORMAT = "special://masterprofile/Thumbnails/Video/%s/%s"

class PluginHandler:
  def isAction(self, params):
    """
    Test if a request is for an action (out of normal flow)
    @param params the request params
    @return: True if it's an action, false otherwise
    """
    pass
  def isCacheable(self, contentType):
    """
    Test if a content type can be cached (or not if it changes too much)
    @param contentType the content type to test for cache usage
    @return: True if it's cacheable content, false otherwise
    """
    pass
  def handle(self, params):
    """
    Handle a request
    @param params the request params
    @return: a list of PluginMovieItem's (or generator)
    """
    pass
  def execute(self, params):
    """
    Execute an action
    @param params the request params
    """
    pass

class PluginMovieItem:
  __listItem = None
  def __init__(self, name, url, mode=None, metadata=None, tags=None):
    self.name = name
    self.url = url
    self.mode = mode
    self.metadata = metadata
    self.tags = tags
    
  def getListItem(self, contextMenu=None):
    if self.__listItem: 
      return self.__listItem
    thumb = ""
    labels = { "title": self.name }
    fanart = None
    if self.metadata is not None and self.metadata.hasCode(): 
      thumb = _preChacheThumbnail(self.metadata.getCover(), "Loading cover for : '%s'" % self.name)
      labels = self.metadata.getLabels()
      if self.metadata.hasFanart():
        fanart = _preChacheThumbnail(self.metadata.getFanart(), "Loading fanart for : '%s'" % self.name)
    self.__listItem = xbmcgui.ListItem(self.name + (self.tags or ""), iconImage=thumb, thumbnailImage=thumb, path=self.url)
    self.__listItem.setInfo(type="Video", infoLabels=labels)
    if fanart is not None:
      self.__listItem.setProperty('fanart_image', fanart)

    if not self.isFolder():
      self.__listItem.setProperty('IsPlayable', 'true')
      
    if contextMenu:
      if not self.isFolder():
        contextMenu.append(("Select source", "XBMC.PlayMedia(%s)" % self.getTargetUrl('selectSource')))
      self.__listItem.addContextMenuItems(contextMenu)
    
    return self.__listItem
   
  def isFolder(self):
    return (self.mode and self.mode != 2)
   
  def getTargetUrl(self, action=None):
    """
    Returns the url for this item to use by XBMC
    @param action: optional action to add to the url
    """
    if self.mode:
      argsMap = {"url": self.url, "mode": str(self.mode), "name": self.name}
      if action:
        argsMap['action'] = action
      return encode(argsMap)
    return self.url 

def _preChacheThumbnail(url, reason="May take a while..."):
  '''
  Cache an image file (cover or backdrop)
  @param url: the url of the image file to cache locally
  @param reason: the reason to inform the user with, since this is may take a while
  @return: the path to the file cached locally
  '''
  if url is None or url == "": return ""
  try:
    filename = xbmc.getCacheThumbName(url)
    filepath = CACHE_PATH_FORMAT % (filename[0], filename)
    log.debug("Got thumbnail path '%s' for file '%s'" % (filename, url))
    if not os.path.isfile(filepath):
      notifier = notification.getUserNotifier("Downloading artwork", reason)
      log.debug("Caching thumbnail '%s' for remote file '%s'" % (filename, url))
      urllib.urlretrieve(url, filepath)
      urllib.urlcleanup()
      notifier.close()
    log.debug("Returning thumb '%s' for file '%s'" % (filename, url))
    return filepath
  except:
    log.exception("Failed to cache thumbnail: %s" % url)
    return url

def list(listItems):
  """
  List some PluginMovieItems in XBMC
  @param listItems: an iterable of PluginMovieItem instances
  """
  for item, count in listItems:
    targetUrl = item.getTargetUrl()
    contextItems = [("Reload listing", "Container.Refresh")]
    loadTargetName = 'Re-load info'
    if item.metadata is None or not item.metadata.hasCode():
      loadTargetName = 'Load info'
    if xbmcplugin.getSetting("metadata-query-skip") == "false":
      contextItems.append((loadTargetName, "XBMC.RunPlugin(%s)" % item.getTargetUrl('loadInfo')))
    listItem = item.getListItem(contextItems)
    xbmcplugin.addDirectoryItem(int(sys.argv[1]), targetUrl, listItem, item.isFolder(), count)

def play(playableItems):
  if playableItems and len(playableItems) > 1:
    playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
    # we need to append the parts to the playlist
    log.debug("Playing items: %s" % str(playableItems))
    position = playlist.getposition()
    otherParts = playableItems[1:]
    try:
      for index in range(len(otherParts)):
        playable = otherParts[index]
        partNumber = index + 2
        log.debug("Appending part %s: %s %s" % (str(partNumber), playable.getTargetUrl(), str(position + partNumber)))
        playlist.add(playable.getTargetUrl(), playable.getListItem(), position + partNumber)
        log.debug("Appended part %s: %s" % (str(partNumber), playable.getTargetUrl()))
    except:
      log.exception("Failed adding items to playlist")
  log.debug("setting resolved url: %s" % playableItems[0].getTargetUrl())
  xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, playableItems[0].getListItem())

def parseArguments(url):
  '''
  Parse the URL arguments into a map
  @param url: a url to parse request arguments from
  @return: a dict with the arguments
  '''
  param = {}
  paramstring = url
  if len(paramstring) >= 2:
    params = url
    cleanedparams = params.replace('?', '')
    if (params[len(params) - 1] == '/'):
      params = params[0:len(params) - 2]
    pairsofparams = cleanedparams.split('&')
    for i in range(len(pairsofparams)):
      splitparams = {}
      splitparams = pairsofparams[i].split('=')
      if (len(splitparams)) == 2:
        param[splitparams[0]] = urllib.unquote_plus(splitparams[1])
  return param

def encode(paramMap):
  '''
  Encode a list of params into a url
  @param paramMap: map of params to encode into url
  @return: encoded url (<base>?<arg1=arg1Val>&...)
  '''
  params = ["%s=%s" % (key, urllib.quote_plus(value)) for key, value in paramMap.items()]
  return sys.argv[0] + "?" + "&".join(params)
